home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Found / ODUtils / Sources / ODMathM.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-25  |  7.0 KB  |  342 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODMath.cpp
  3.  
  4.     Contains:    Math routines (fixed-point and wide) for OpenDoc.
  5.  
  6.     Owned by:    Jens Alfke
  7.     Written by:    Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good,
  8.                 Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink,
  9.                 Chris Yerga
  10.  
  11.     Copyright:    © 1987 - 1995 by Apple Computer, Inc., all rights reserved.
  12.  
  13.     Notes:
  14.         The PowerPC definitions of many of these functions are already built
  15.         into the Mac OS, so they are compiled here only for 68k. Likewise,
  16.         the 68k definitions of some of these functions are coded in assembly
  17.         language in ODMathM.a, and they are compiled here only for PowerPC.
  18.     
  19.     To Do:
  20.     In Progress:
  21.         
  22. */
  23.  
  24.  
  25. #ifndef _ODMATH_
  26. #include "ODMath.h"
  27. #endif
  28.  
  29. #ifndef __FIXMATH__
  30. #include <FixMath.h>
  31. #endif
  32.  
  33.  
  34. //=============================================================================
  35. // Constants
  36. //=============================================================================
  37.  
  38.  
  39. #define longSize        32
  40. #define wideSize        64
  41.  
  42. #define highBit            ((ODULong) 0x80000000)
  43.  
  44.  
  45. //=============================================================================
  46. // Wide Math For Non-PowerPC
  47. //=============================================================================
  48.  
  49.  
  50. #if !defined(powerc) && !defined(__powerc)
  51.  
  52. #ifdef __MWERKS__
  53. #if 0
  54. extern asm short ODFirstBit(long x)
  55. {
  56.             machine        68020
  57.             move.l            (sp)+,a0        //        get return address
  58.             move.l            (sp),d0            //        get x
  59.             bfffo            d0{0:0},d1
  60.             moveq            #31,d0
  61.             sub.w            d1,d0
  62.             addq.l            #4,sp
  63.             jmp                (a0)
  64. }
  65. #endif
  66.  
  67. extern asm ODSLong ODWideDivide(const ODWide *dividend,
  68.                             ODSLong divisor, ODSLong *remainder)
  69. {
  70.             machine        68020
  71.             machine        68881
  72.             link            a6,#-2
  73.             moveq        #-1,d0
  74.             cmp.l        16(a6),d0            //    if (rem == (void *)-1)
  75.             seq            -1(a6)                //    set check
  76.             bne.s        @noCheck
  77.             clr.l            16(a6)            //        rem = 0
  78. @noCheck:
  79.             move.l        8(a6),a0            //    get num
  80.             move.l        (a0)+,d1
  81.             move.l        (a0),d0
  82.             move.l        12(a6),d2            //    get denom
  83.             beq.s        @div0
  84.             bpl.s            @1
  85.             neg.l            d2
  86. @1:            tst.l            16(a6)            //        check rem
  87.             bne.s        @3
  88.             lsr.l            #1,d2
  89.             tst.l            d1
  90.             bpl.s            @2
  91.             neg.l            d2
  92. @2:            add.l            d2,d0
  93.             bfexts        d2{0:1},d2
  94.             addx.l        d2,d1
  95. @3:            divs.l        12(a6),d1:d0
  96.             bvc.s        @ok
  97.             move.l        12(a6),d2
  98. @div0:        tst.b            -1(a6)            //        check check
  99.             bne.s        @div1
  100.             eor.l            d1,d2
  101.             bmi.s        @div1
  102.             move.l        #0x7FFFFFFF,d0
  103.             bra.s        @div2
  104. @div1:        move.l        #0x80000000,d0
  105. @div2:        move.l        #0x80000000,d1
  106. @ok:        move.l        16(a6),d2            //    get rem
  107.             beq.s        @done
  108.             move.l        d2,a0
  109.             move.l        d1,(a0)
  110. @done:        unlk        a6
  111.             rtd            #12
  112. }
  113.  
  114. extern asm ODULong ODWideSquareRoot( const ODWide *src )
  115. {
  116.             machine        68020
  117.             machine        68881
  118.             move.l        (sp)+,a0
  119.             move.l        #0x80000000,d1
  120.             
  121.             // fmove.l        d1,fp1
  122.             opword        0xF201, 0x4080
  123.             
  124.             move.l        (sp),a1                //        Get src
  125.             move.l        (a1)+,d0            //        Get hi long
  126.             add.l        d1,d0                //        Offset for sign
  127.  
  128.             // fmove.l        d0,fp0                //        Move to FP0
  129.             opword        0xF200, 0x4000
  130.             
  131.             // fsub.x        fp1,fp0                //        Compensate for offset
  132.             opword        0xF200, 0x0428
  133.             
  134.             // fscale.w    #32,fp0                //        Shift by 32
  135.             opword        0xF23C, 0x5026, 0x0020
  136.             
  137.             move.l        (a1),d0                //        Get lo long
  138.             add.l        d1,d0                //        Offset for sign
  139.             
  140.             // fadd.l        d0,fp0                //        Add to FP0
  141.             opword        0xF200, 0x4022
  142.             
  143.             // fsub.x        fp1,fp0                //        Compensate for offset
  144.             opword        0xF200, 0x0428
  145.             
  146.             // fsqrt.x        fp0                    //        The whole point
  147.             opword        0xF200, 0x0004
  148.             
  149.             // fadd.x        fp1,fp0                //        Offset for sign
  150.             opword        0xF200, 0x0422
  151.             
  152.             // fmove.l        fp0,d0                //        Pass result to D0
  153.             opword        0xF200, 0x6000
  154.             
  155.             sub.l        d1,d0                //        Compensate for offset
  156.             addq.l        #4,sp
  157.             jmp            (a0)
  158. }
  159.  
  160.  
  161.  
  162.  
  163.  
  164. #endif
  165.  
  166.  
  167.  
  168. ODFixed lastSinCosAngle = 0;    // Globals used in .a file
  169. ODFract lastSine = 0,
  170.         lastCosine = kODFract1;
  171.  
  172.  
  173. // Wide math routines are already in the OS on Power Macs.
  174.  
  175.  
  176. ODSShort ODWideCompare(const ODWide *a, const ODWide *b)
  177. {
  178.     if (a->hi > b->hi) return 1;
  179.     if (a->hi < b->hi) return -1;
  180.     if (a->lo > b->lo) return 1;
  181.     if (a->lo < b->lo) return -1;
  182.     return 0;
  183. }
  184.  
  185.  
  186. ODWide *
  187. ODWideNegate(register ODWide *dst)
  188. {
  189.     if (dst->lo) {
  190.         dst->lo = -dst->lo;
  191.         dst->hi = ~dst->hi;
  192.     } else
  193.         dst->hi = -dst->hi;
  194.     return dst;
  195. }
  196.  
  197.  
  198. /* Shift a ODWide to the right (shift > 0) or left (shift < 0) */
  199. ODWide *
  200. ODWideShift(register ODWide *src, register ODSShort shift)
  201. {
  202.     register long x = src->hi, y = src->lo;
  203.     if (shift > 0)
  204.         if (shift >= longSize)
  205.         {    src->hi = -(x < 0);
  206.             src->lo = x >> shift - longSize;
  207.             if (shift == longSize && y < 0 || x << wideSize - shift < 0)
  208.                 ++src->lo || ++src->hi;
  209.         }
  210.         else
  211.         {    src->hi = x >> shift;
  212.             src->lo = x << longSize - shift | (unsigned long)y >> shift;
  213.             if (y << longSize - shift < 0)
  214.                 ++src->lo || ++src->hi;
  215.         }
  216.     else if ( (shift = -shift) != 0 )
  217.         if (shift >= longSize)
  218.         {    src->hi = y << shift - longSize;
  219.             src->lo = 0;
  220.         }
  221.         else
  222.         {    src->hi = x << shift | (unsigned long)y >> longSize - shift;
  223.             src->lo = y << shift;
  224.         }
  225.     return src;
  226. }
  227.  
  228.  
  229. ODWide *
  230. ODWideAdd(register ODWide *dst, register const ODWide *src)
  231. {
  232.     dst->lo += src->lo;
  233.     if (dst->lo < src->lo)
  234.         dst->hi += src->hi + 1;
  235.     else
  236.         dst->hi += src->hi;
  237.     return dst;
  238. }
  239.  
  240.  
  241. ODWide *
  242. ODWideSubtract(register ODWide *dst, register const ODWide *src)
  243. {
  244.     if (dst->lo < src->lo)
  245.         dst->hi -= src->hi + 1;
  246.     else
  247.         dst->hi -= src->hi;
  248.     dst->lo -= src->lo;
  249.     return dst;
  250. }
  251.  
  252.  
  253. // ODWideMultiply and ODWideDivide are in ODMathM.a
  254.  
  255.  
  256.  
  257. //=============================================================================
  258. // Wide Math  & Bit-Twiddling For PowerPC
  259. //=============================================================================
  260.  
  261.  
  262. #else /*powerc*/
  263.  
  264.  
  265. ODSShort
  266. ODFirstBit( ODSLong x )                // JPA: I wrote this from scratch
  267. {
  268.     ODSShort bit = 0;
  269.  
  270.     if (x == 0)
  271.         return -1;
  272.  
  273.     if (x >= 1UL << 16)
  274.         bit += 16, x >>= 16;
  275.     if (x >= 1UL << 8)
  276.         bit += 8, x >>= 8;
  277.     if (x >= 1UL << 4)
  278.         bit += 4, x >>= 4;
  279.     if (x >= 1UL << 2)
  280.         bit += 2, x >>= 2;
  281.     if (x >= 1UL << 1)
  282.         bit += 1;
  283.     return bit;
  284. }
  285.  
  286. #undef ODWideCompare
  287. ODSShort ODWideCompare(const ODWide *a, const ODWide *b)
  288. {
  289.     return (ODSShort) WideCompare(a,b);
  290. }
  291.  
  292. #undef ODWideNegate
  293. ODWide * ODWideNegate(register ODWide *dst)
  294. {
  295.     return (ODWide*) WideNegate(dst);
  296. }
  297.  
  298. #undef ODWideShift
  299. ODWide * ODWideShift(register ODWide *src, register ODSShort shift)
  300. {
  301.     return (ODWide*) WideShift(src,(long)shift);
  302. }
  303.  
  304. #undef ODWideAdd
  305. ODWide * ODWideAdd(register ODWide *dst, register const ODWide *src)
  306. {
  307.     return (ODWide*) WideAdd(dst,src);
  308. }
  309.  
  310. #undef ODWideSubtract
  311. ODWide * ODWideSubtract(register ODWide *dst, register const ODWide *src)
  312. {
  313.     return (ODWide*) WideSubtract(dst,src);
  314. }
  315.  
  316. #undef ODWideDivide
  317. ODSLong ODWideDivide( register const ODWide *dividend,
  318.                             ODSLong divisor, ODSLong *remainder)
  319. {
  320.     return (ODSLong) WideDivide(dividend,divisor,remainder);
  321. }
  322.  
  323. #undef ODWideSquareRoot
  324. ODULong ODWideSquareRoot(register const ODWide *src)
  325. {
  326.     return (ODULong) WideSquareRoot(src);
  327. }
  328.  
  329. ODFract
  330. ODFractSinCos( ODFixed angle, ODFract *cos )
  331. {
  332.     // I have no idea whether FracSin and FracCos are native ... if not,
  333.     // this will be much slower than it could be. But is this every going
  334.     // to be a bottleneck?   [OPTIMIZATION]
  335.     
  336.     if( cos )
  337.         *cos = FracCos(angle);
  338.     return FracSin(angle);
  339. }
  340.  
  341. #endif /*powerc*/
  342.